<?php

namespace App\Http\Middleware;
use App\Common\Libs\ArrayHelper;
use App\Consts\ExceptionCodeConst;
use App\Consts\GlobalConst;
use Closure;

use Illuminate\Http\Request;

class SignAuthenticate
{

    /**
     * Handle an incoming request.
     * 参数加密签名认证
     * @param \Illuminate\Http\Request $request
     * @param \Closure $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next)
    {
        // 本地和开发环境跳过参数验证
        if (isLocal() || isDev()) {
            return $next($request);
        }

        // 获取参数
        $bodyForm = $request->all();
        try {
            // 验证客户端参数中是否含有 timestamp 和 sign
            if (empty($bodyForm['timestamp']) || empty($bodyForm['sign'])) {
                throw new \Exception(lang('Sign error'), ExceptionCodeConst::SIGN_PLATFORM_ERROR);
            }
            // 验证客户端时间和服务器时间是否 > 30s
            if (time() - (int)$bodyForm['timestamp'] > GlobalConst::SIGN_EXPIRED_TIME) {
                throw new \Exception(lang('Sign error'), ExceptionCodeConst::SIGN_TIME_OVER);
            }
            $sign = $bodyForm['sign'];
            // 去掉参数中的sign
            $bodyForm = ArrayHelper::remove($bodyForm, 'sign');
            // 签名不验证 file
            if (isset($bodyForm['file'])) {
                unset($bodyForm['file']);
            }

            // 按ASCII码升序排序
            ksort($bodyForm);
            // 将其他参数进行加密
            $raw = '';
            foreach ($bodyForm as $key => $value) {
                $raw .= $key . '=' . $value . '&';
            }
            // 首位拼接，各个端的secret（随机字符串）
            $webSecret = GlobalConst::SECRET_MSG_CENTER;
            $raw = $raw . '&key=' . $webSecret;

            // 加密字符串去掉 换行符 和 空格
            $raw = str_replace([PHP_EOL, "\t", ' '], '', $raw);
            $check = strtoupper(md5($raw));

            if ($check !== $sign) {
                $request->merge(['mime' => $check]);
                throw new \Exception(lang('Sign error'), ExceptionCodeConst::SIGN_VERIFY_FAIL);
            }
        } catch (\Exception $e) {
            return appThrow($e);
        }

        return $next($request);
    }


}